#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/11/19 12:05
# @Author : 闫峰
# @File    : mongodb_utils.py
import json
from datetime import datetime
from typing import Union
import pymongo
from urllib.parse import quote


class MongoDBLink:
    def __init__(self, uri: str, dbname: str, coll_name: str):

        self.dbname = dbname
        self.coll_name = coll_name
        url_list = uri.split(":")
        pass_word_ip = url_list[2]
        pass_word, ip = pass_word_ip.split("@")
        pass_word = quote(pass_word)
        pass_word_ip = pass_word + "@" +  ip
        url_list[2] = pass_word_ip
        uri = ":".join(url_list)
        self.uri = uri
        self.client = pymongo.MongoClient(uri)
        # with self.client:
        #     self.db = self.client[self.dbname]
        #     self.collection = self.db[self.coll_name]
        self.db = self.client[dbname]
        self.collection = self.db[self.coll_name]
        # self.collection.find()

    def select(self, sql, field_):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        res = self.collection.find(sql, field_)
        return [one for one in res]

    def get_index(self):
        index_info = self.collection.index_information()
        # 打印索引信息
        for index_name, index_spec in index_info.items():
            print(index_name, ":", index_spec)

    def select_skip_limit(self, query, projection, page, limit):
        """
        分页查询并验证数据
        :param query: MongoDB 查询过滤条件
        :param projection: 字段选择
        :param page: 当前页码
        :param limit: 每页记录数
        :return: 验证后的查询结果列表
        """
        skip = (page - 1) * limit
        result = self.collection.find(query, projection).skip(skip).limit(limit)
        return [self.verify(doc) for doc in result]


    def select_skip_projection_limit(self, sql, projection, sort_field, limit):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        res = self.collection.find(sql, projection).sort(sort_field, 1).limit(limit)
        return [self.verify(one) for one in res]

    def filter_projection_sort_limit(self, filter, projection, sort, limit):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        res = self.collection.find(filter, projection).sort(sort).limit(limit)
        return [self.verify(one) for one in res]

    def select_skip_limit1(self, sql, asc, skip, limit):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        sort = [(asc, pymongo.ASCENDING)]
        start = (skip - 1) * limit
        res = self.collection.find(sql, sort=sort, limit=limit, skip=start)
        return [self.verify(one) for one in res]

    def select2(self, sql,field):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        res = self.collection.find(sql, field).skip(0)
        return [self.verify(one) for one in res]
    def selectTuple(self, sql, field):
        """
        查询
        :param sql:   mongodb查询语句
        :return:
        """
        res = self.collection.find(sql, field, ).skip(0)
        resTuple = []
        for i in res:
            resTuple.append((i["sku"],))
        return resTuple

    def aggregate(self, pipeline):
        res = self.collection.aggregate(pipeline)
        return [self.verify(one) for one in res]

    def paginate(self, pipeline, page_num, page_size):
        # 使用 cursor 手动控制查询
        cursor = self.collection.aggregate(pipeline, allowDiskUse=True, cursor={})
        cursor.skip((page_num - 1) * page_size).limit(page_size)
        for doc in cursor:
            print(doc)

    def verify(self, result: dict) -> Union[dict, None]:
        """验证结果能否被json.dumps序列化"""
        # 尝试变成字符串，解决datetime 无法被json 序列化问题
        try:
            json.dumps(result)
        except TypeError:  # TypeError: Object of type datetime is not JSON serializable
            for k, v in result.items():
                if isinstance(v, datetime):
                    result[k] = str(v)
        return result

    def insert_one(self, document):
        self.collection.insert_one(document=document)

    def insert_many(self, documents):
        self.collection.insert_many(documents=documents)

    def delete_one(self, filter):
        self.collection.delete_one(filter=filter)

    def delete_many(self, filter):
        self.collection.delete_many(filter=filter)

    def count(self, filter):
        return self.collection.count(filter=filter)

    def insert_many_by_json(self, file_path):
        with open(file_path, 'r') as f:
            data = json.load(f)
            res = self.insert_many(data['RECORDS'])

    def delete_collectio(self):
        self.collection.drop()


